﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using GRMS.App_Data;

namespace GRMS.App_Code
{
    class ActorCommands
    {
        public static string CharacterCommands(string input, Session sesh, bool combat)
        {
            //Getting Character
            if (input.Contains("Get Characters"))
            {
                string ID = input.Split(' ').Length > 1 ? input.Split(' ')[2] : string.Empty;
                CharacterGetList cgl = new CharacterGetList(new GameSessionDataContext(), Int32.Parse(new UserGetList(new GameSessionDataContext(), ID)[0].USERID.ToString()));
                string result = "Characters available for " + ID;
                foreach (CharacterGet cg in cgl)
                    result += "<br/>" + cg.CharacterName;

                return result;
            }
            //Selecting Character
            else if (input.Contains("Select "))
            {
                string CHAR = input.Split(' ').Length > 1 ? input.Split(' ')[1] : string.Empty;
                Character c = new Character(sesh);

                try
                {
                    c.ID = CHAR;
                    c.Load(CHAR, string.Format("/App_Data/Rules/{0}.xml", CHAR), sesh);
                    if (!sesh.HasCharacter(CHAR))
                        sesh.AddCharacter(c, input.Split(' ')[2]);

                    return c.Get("name").Value + " loaded for " + input.Split(' ')[2];
                }
                catch
                {
                    return "Character does not exist.";
                }
            }
            //Getting actions
            else if (input.Contains("Get Actions"))
            {
                Character c = sesh.GetCharacter(input.Split(' ')[2]);
                Dictionary<string, string> dict;
                string result = "";
                if (combat)
                {
                    result += "Combat actions for " + c.Get("name").Value + "<br/>";
                    dict = c.GetActions("", "combat");
                }
                else
                {
                    result += "Actions for " + c.Get("name") + "<br/>";
                    dict = c.GetActions("", "non-combat");
                }

                foreach (KeyValuePair<string, string> kvp in dict)
                    result += kvp.Key + " " + kvp.Value + "<br/>";

                return result;
            }
            //Preforming actions
            else
            {
                try
                {
                    string[] split = input.Split(' ');
                    string target = split[1];

                    Character c = sesh.GetCharacter(split[split.Length - 2]);
                    Dictionary<string, string> dict;
                    if (combat)
                        dict = c.GetActions("", "combat");
                    else
                        dict = c.GetActions("", "non-combat");

                    string act = input.Replace(split[0], "").Replace(split[1], "").Replace(split[split.Length - 2], "").Replace(split[split.Length - 1], "").Trim();

                    if (((ActionSequencer)sesh.GetGlobal("CombatList")).IsActive && ((ActionSequencer)sesh.GetGlobal("CombatList")).CurrentActor() == c.Get("name").Value)
                    {
                        ActionEventRequest AER = c.GetEventRequest(act, target);
                        sesh.SetGlobal("ActionEventRequest", AER);
                        ActionEventFactory AEF = new ActionEventFactory(sesh);
                        ActionEventHandler AEH = new ActionEventHandler(sesh);
                        ActionEvent AE = AEF.GenerateActionEvent(AER);
                        string result = AEH.ProcessActionEvent(AE);
                        if (result.Contains("succeeded") || result.Contains("exceptionally"))
                        {
                            AER = c.GetEventRequest(act, "Damage");
                            AE = AEF.GenerateActionEvent(AER);
                            result += "<br/>" + AEH.ProcessActionEvent(AE);

                            Character targ = sesh.GetCharacter(target);
                            string health = targ.Get("Life Points").Value.ToString();

                            Regex stun = new Regex("Stun: [0-9]+");
                            string stunStr = stun.Match(health).Value;
                            int stunV = Int32.Parse(stunStr.Replace("Stun: ", ""));
                            Regex wound = new Regex("Wound: [0-9]+");
                            string woundStr = wound.Match(health).Value;
                            int woundV = Int32.Parse(woundStr.Replace("Wound: ", ""));
                            Regex dmg = new Regex("[0-9]+ damage");
                            int dmgV = Int32.Parse(dmg.Match(result).Value.Replace(" damage", ""));

                            int stunV1 = dmgV / 2;
                            int woundV1 = dmgV / 2;
                            if (dmgV / 2 * 2 != dmgV)
                                stunV1--;

                            health = health.Replace(stunStr, stunStr.Replace(stunV.ToString(), stunV1.ToString())).Replace(woundStr, woundStr.Replace(woundV.ToString(), woundV1.ToString()));
                            targ.Properties["Life Points"].Value = health;

                            sesh.SaveCharacter(targ);

                            if (stunV1 - woundV1 <= 0)
                            {
                                ActionSequencer seq = (ActionSequencer)sesh.GetGlobal("CombatList");
                                seq.IsActive = false;
                                sesh.SetGlobal("CombatList", seq);

                                result += string.Format("  {0} falls uncontious, {1} wins!<br/>", targ.ID, split[split.Length - 2]);
                            }
                            else
                            {
                                ActionSequencer seq = (ActionSequencer)sesh.GetGlobal("CombatList");
                                seq.Next();
                                sesh.SetGlobal("CombatList", seq);

                                result += seq.Header();
                            }
                        }
                        return result;
                    }
                    else if (((ActionSequencer)sesh.GetGlobal("CombatList")).IsActive && ((ActionSequencer)sesh.GetGlobal("CombatList")).CurrentActor() != c.Get("name").Value)
                    {
                        ActionEventRequest AER = c.GetEventRequest(act, split[2]);
                        sesh.SetGlobal("ActionEventRequest", AER);
                        ActionEventFactory AEF = new ActionEventFactory(sesh);
                        ActionEvent AE = AEF.GenerateActionEvent(AER);
                        ActionEventHandler AEH = new ActionEventHandler(sesh);
                        return AEH.ProcessActionEvent(AE);
                    }
                    else
                    {
                        ActionEventRequest AER = c.GetEventRequest(act, "");
                        ActionEventFactory AEF = new ActionEventFactory(sesh);
                        ActionEvent AE = AEF.GenerateActionEvent(AER);
                        ActionEventHandler AEH = new ActionEventHandler(sesh);
                        return AEH.ProcessActionEvent(AE);
                    }

                }
                catch { return "Invalid Action"; }
            }

        }

        public static string GMCommands(string input, Session sesh)
        {
            //Getting NPC Templates
            if (input.Contains("Get NPCs "))
            {
                Dictionary<string, Hashtable> dict = XMLReader.GetValuesFrom("/App_Data/Rules/NPCs.xml", "NPCs NPC", sesh);
                string result = "NPC's Available";

                foreach (KeyValuePair<string, Hashtable> kvp in dict)
                {
                    result += string.Format("<br/>{0}", kvp.Key);
                }

                return result;
            }
            //Creating NPCs
            else if (input.Contains("Create "))
            {
                string CHAR = input.Split(' ').Length > 1 ? input.Split(' ')[1] : string.Empty;
                Character c = new Character(sesh);
                int count = 1;

                while (sesh.HasCharacter(CHAR + count))
                    count++;

                try
                {
                    c.ID = CHAR + count;
                    c.Load(CHAR + count, string.Format("/App_Data/Rules/{0}.xml", CHAR), sesh);
                    c.Properties["name"].Value = c.Get("name").Value + count;
                    sesh.AddCharacter(c, input.Split(' ')[2]);
                    return c.Get("name").Value + " loaded for GM";
                }
                catch
                {
                    return "NPC does not exist.";
                };
            }
            //Reviving actor
            else if (input.Contains("Revive "))
            {
                Character c = sesh.GetCharacter(input.Split(' ')[1]);
                c.Properties["Life Points"].Reset();

                return c.Get("Life Points").Value + "<br/>" + c.Get("name").Value + " has been revived.";
            }
            //Starting Combat
            else if (input.Contains("Combat Start "))
            {
                string[] lst = input.Replace("Combat Start ", "").Replace(" GM", "").Split(' ');

                sesh.SetGlobal("CombatList", new ActionSequencer(lst, sesh));

                return "Combat Started<br/><br/>" + ((ActionSequencer)sesh.GetGlobal("CombatList")).Header();
            }
            //Passing combat actions to NPC(s)
            else
            {
                return CharacterCommands(input, sesh, true);
            }
        }
    }
}
